package com.zxd.interview.eightthread.uncaughtexception;


/**
 * 主线程可以随意的catch异常，但是子线程却不行
 *
 * 1. 主线程使用传统方法可以捕获线程
 * 2. 主线程catch主四个子线程的异常，四个线程抛出异常，发现catch不住
 * 3. thread1.setUncaughtExceptionHandler(new MyCaughtExceptionHandler("线程 1")); 设置自定义的捕获器捕获异常
 */
public class UncaughtExceptionTest implements Runnable {

    public static void main(String[] args) {

        // 主线程可以随意的catch异常，但是子线程却不行
//        try {
//            int i = 1 / 0;
//        } catch (Exception e) {
//            System.out.println("主线程异常" + e.getLocalizedMessage());
//        }
        /**
         主线程异常/ by zero
         */
        System.out.println("\n");

        // 最高效的写法，直接在最顶层的主线程设置捕获器，子线程抛出异常会调用parent的捕获器
        Thread.setDefaultUncaughtExceptionHandler(new MyCaughtExceptionHandler("主线程自定义捕获器"));

//        try {
            Thread thread1 = new Thread(new UncaughtExceptionTest());
            // 如何让主线程可以处理子线程，通过设置 MyCaughtExceptionHandler 方式实现
//            thread1.setUncaughtExceptionHandler(new MyCaughtExceptionHandler("线程 1"));
            thread1.setName("线程1");
            thread1.start();

            Thread thread2 = new Thread(new UncaughtExceptionTest());
//            thread2.setUncaughtExceptionHandler(new MyCaughtExceptionHandler("线程 2"));
            thread2.setName("线程2");
            thread2.start();

            Thread thread3 = new Thread(new UncaughtExceptionTest());
//            thread3.setUncaughtExceptionHandler(new MyCaughtExceptionHandler("线程 3"));
            thread3.setName("线程3");
            thread3.start();


            Thread thread4 = new Thread(new UncaughtExceptionTest());
//            thread4.setUncaughtExceptionHandler(new MyCaughtExceptionHandler("线程 4"));
            thread4.setName("线程4");
            thread4.start();
//        } catch (Exception e) {
            // 子线程抛出异常，主线程捕获不到
//            System.out.println("主线程捕获子线程异常" + e.getLocalizedMessage());

//        }



    }

    @Override
    public void run() {

//        try {
            throw new RuntimeException(Thread.currentThread().getName() + " 抛出异常");
//        } catch (RuntimeException e) {
            // 子线程里面处理异常的办法虽然可行，但是需要考虑很多所有的异常情况：
//            System.out.println("捕获子线程异常" + e.getLocalizedMessage());
//        }
        /**
         捕获子线程异常线程4 抛出异常
         捕获子线程异常线程2 抛出异常
         捕获子线程异常线程3 抛出异常
         捕获子线程异常线程1 抛出异常
         */
    }/**
     子线程处理：
     所有的异常在对应的线程当中处理

     Exception in thread "线程1" Exception in thread "线程4" Exception in thread "线程2" Exception in thread "线程3" java.lang.RuntimeException: 线程1 抛出异常
     at com.zxd.interview.eightthread.uncaughtexception.UncaughtExceptionTest.run(UncaughtExceptionTest.java:52)
     at java.base/java.lang.Thread.run(Thread.java:834)
     java.lang.RuntimeException: 线程2 抛出异常
     at com.zxd.interview.eightthread.uncaughtexception.UncaughtExceptionTest.run(UncaughtExceptionTest.java:52)
     at java.base/java.lang.Thread.run(Thread.java:834)
     java.lang.RuntimeException: 线程4 抛出异常
     at com.zxd.interview.eightthread.uncaughtexception.UncaughtExceptionTest.run(UncaughtExceptionTest.java:52)
     at java.base/java.lang.Thread.run(Thread.java:834)
     java.lang.RuntimeException: 线程3 抛出异常
     at com.zxd.interview.eightthread.uncaughtexception.UncaughtExceptionTest.run(UncaughtExceptionTest.java:52)
     at java.base/java.lang.Thread.run(Thread.java:834)

     Process finished with exit code 0
     */
}
